package go_command

import (
    "reflect"
    "errors"
    "fmt"
)

// 保存方法
var funcs map[string]reflect.Value

func init() {
    funcs = make(map[string]reflect.Value)
}

// 注册命令
func RegisterCommand(routes map[string]interface{}) {
    for path, fn := range routes{
        bind(path, fn)
    }
}

// 绑定路由，通过反射机制
func bind(command string, fn interface{}) (err error) {
    defer func() {
        if err := recover(); err != nil {
            err = errors.New(command + " is not callable.")
        }
    }()
    v := reflect.ValueOf(fn)
    v.Type().NumIn()
    funcs[command] = v
    return
}

// 执行
func Call(command string, params ...interface{}) (result []reflect.Value, err error) {
    fn, ok := funcs[command]
    if !ok {
        return nil, errors.New("unknown command: " + command)
    }
    if len(params) != fn.Type().NumIn() {
        return nil, errors.New("params not adapted")
    }

    in := make([]reflect.Value, len(params))
    for k, param := range params {
        in[k] = reflect.ValueOf(param)
    }
    result = fn.Call(in)
    return result, nil
}

// 打印使用方法
func Usage()  {
    fmt.Println("支持的命令:")
    for command, fn := range funcs {
        fmt.Print("./console " + command + " ")
        for i:=0; i<fn.Type().NumIn(); i++ {
            // 只能获取到参数类型，参数名无法获取
            fmt.Print(fn.Type().In(i).Name()+" ")
        }
        fmt.Print("\n")
    }
}
